package com.zp.business.impl.outpFees;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zp.base.api.RemoteClinicItemDictService;
import com.zp.base.api.RemoteSerialNumberUtils;
import com.zp.business.api.prescription.PrescriptionApply;
import com.zp.business.api.prescription.PrescriptionItem;
import com.zp.business.api.prescription.vo.PrescriptionApplyVo;
import com.zp.business.api.prescription.vo.PrescriptionItemVo;
import com.zp.business.entity.clinicOrder.ClinicOrders;
import com.zp.business.entity.clinicOrder.ClinicOrdersCost;
import com.zp.business.entity.clinicOrder.OutpTreatRec;
import com.zp.business.entity.clinicOrder.bo.ClinicOrdersBo;
import com.zp.business.entity.clinicOrder.bo.ClinicOrdersCostBo;
import com.zp.business.entity.clinicOrder.vo.ClinicOrdersCostVo;
import com.zp.business.entity.clinicOrder.vo.ClinicOrdersVo;
import com.zp.business.entity.exam.ExamApply;
import com.zp.business.entity.exam.ExamItem;
import com.zp.business.entity.exam.vo.ExamApplyVo;
import com.zp.business.entity.exam.vo.ExamItemVo;
import com.zp.business.entity.lab.LabApply;
import com.zp.business.entity.lab.LabItem;
import com.zp.business.entity.lab.vo.LabApplyVo;
import com.zp.business.entity.lab.vo.LabItemVo;
import com.zp.business.entity.outpFees.OutpFeesDetail;
import com.zp.business.entity.outpFees.OutpFeesMaster;
import com.zp.business.entity.outpFees.OutpFeesPaymentsMoney;
import com.zp.business.entity.outpFees.bo.FeesParamBo;
import com.zp.business.entity.outpFees.bo.OutpFeesMasterBo;
import com.zp.business.entity.outpFees.bo.OutpFeesPaymentsMoneyBo;
import com.zp.business.entity.outpFees.vo.OutpFeesDetailVo;
import com.zp.business.entity.outpFees.vo.OutpFeesMasterVo;
import com.zp.business.entity.outpFees.vo.OutpFeesPaymentsMoneyVo;
import com.zp.business.mapper.clinicOrder.ClinicOrdersCostMapper;
import com.zp.business.mapper.clinicOrder.ClinicOrdersMapper;
import com.zp.business.mapper.clinicOrder.OutpTreatRecMapper;
import com.zp.business.mapper.exam.ExamApplyMapper;
import com.zp.business.mapper.exam.ExamItemMapper;
import com.zp.business.mapper.lab.LabApplyMapper;
import com.zp.business.mapper.lab.LabItemMapper;
import com.zp.business.mapper.outpFees.OutpFeesDetailMapper;
import com.zp.business.mapper.outpFees.OutpFeesMasterMapper;
import com.zp.business.mapper.outpFees.OutpFeesPaymentsMoneyMapper;
import com.zp.business.mapper.prescription.PrescriptionApplyMapper;
import com.zp.business.mapper.prescription.PrescriptionItemMapper;
import com.zp.business.service.clinicOrder.IClinicOrdersCostService;
import com.zp.business.service.clinicOrder.IClinicOrdersService;
import com.zp.business.service.outpFees.IOutpFeesMasterService;
import com.zp.business.service.outpFees.IOutpFeesPaymentsMoneyService;
import com.zp.common.core.constant.BaseConstants;
import com.zp.common.core.constant.CacheNames;
import com.zp.common.core.constant.SerialNumberConstants;
import com.zp.common.core.constant.UserConstants;
import com.zp.common.core.utils.DateUtils;
import com.zp.common.core.utils.StringUtils;
import com.zp.common.myBatis.core.page.PageQuery;
import com.zp.common.myBatis.core.page.TableDataInfo;
import com.zp.common.redis.utils.CacheUtils;
import com.zp.common.satoken.utils.LoginHelper;
import com.zp.system.api.entity.SysDept;
import com.zp.system.api.entity.SysUser;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 门诊收费记录主Service业务层处理
 *
 * @author zhang peng
 * @ date 2024-04-12
 */
@RequiredArgsConstructor
@Service
public class OutpFeesMasterServiceImpl implements IOutpFeesMasterService {

    private final OutpFeesMasterMapper baseMapper;
    private final OutpFeesDetailMapper outpFeesDetailMapper;
    private final OutpFeesPaymentsMoneyMapper outpFeesPaymentsMoneyMapper;
    private final ClinicOrdersMapper clinicOrdersMapper;
    private final ClinicOrdersCostMapper clinicOrdersCostMapper;
    private final OutpTreatRecMapper outpTreatRecMapper;
    private final ExamApplyMapper examApplyMapper;
    private final ExamItemMapper examItemMapper;
    private final LabApplyMapper labApplyMapper;
    private final LabItemMapper labItemMapper;
    private final PrescriptionApplyMapper prescriptionApplyMapper;
    private final PrescriptionItemMapper prescriptionItemMapper;
    @DubboReference
    private RemoteClinicItemDictService remoteClinicItemDictService;


    /**
     * 用户信息
     */
    static Map<String, SysUser> sysUserMap = CacheUtils.get(CacheNames.SYS_USER);

    static Map<String, SysDept> sysDeptMap = CacheUtils.get(CacheNames.SYS_DEPT);

    private final IClinicOrdersService clinicOrdersService;
    private final IClinicOrdersCostService clinicOrdersCostService;
    @DubboReference
    private RemoteSerialNumberUtils remoteSerialNumberUtils;
    private final IOutpFeesPaymentsMoneyService outpFeesPaymentsMoneyService;


    /**
     * 查询门诊收费记录主
     */
    @Override
    public OutpFeesMasterVo queryById(String outpFeesMasterId) {
        return baseMapper.selectVoById(outpFeesMasterId);
    }

    /**
     * 查询门诊收费记录主列表(分页)
     */
    @Override
    public TableDataInfo<OutpFeesMasterVo> queryPageList(OutpFeesMasterBo bo, PageQuery pageQuery) {
        Map<String, Object> params = bo.getParams();
        if (params.get("beginTime") != null && params.get("endTime") != null) {
            bo.setBeginTime(DateUtils.dateTime(params.get("beginTime")));
            bo.setEndTime(DateUtils.dateTime(params.get("endTime")));
        }
        Page<OutpFeesMasterVo> result = baseMapper.selectVoPage(pageQuery.build(), bo);
        result.getRecords().forEach(outpFeesMaster -> {
            OutpFeesPaymentsMoneyBo paymentsMoneyBo = new OutpFeesPaymentsMoneyBo();
            paymentsMoneyBo.setFeesNo(outpFeesMaster.getFeesNo());
            paymentsMoneyBo.setOrgId(outpFeesMaster.getOrgId());
            outpFeesMaster.setPaymentsMoneyVoList(outpFeesPaymentsMoneyService.queryList(paymentsMoneyBo));
        });
        return TableDataInfo.build(result);
    }


    /**
     * 查询门诊收费记录主列表(不分页)
     */
    @Override
    public List<OutpFeesMasterVo> queryList(OutpFeesMasterBo bo) {
        initChargeFlagArray(bo);
        List<OutpFeesMasterVo> outpFeesMasterVos = baseMapper.selectVoPage(bo);
        outpFeesMasterVos.forEach(outpFeesMasterVo -> {
            OutpFeesPaymentsMoneyBo paymentsMoneyBo = new OutpFeesPaymentsMoneyBo();
            paymentsMoneyBo.setFeesNo(outpFeesMasterVo.getFeesNo());
            paymentsMoneyBo.setOrgId(outpFeesMasterVo.getOrgId());
            outpFeesMasterVo.setPaymentsMoneyVoList(outpFeesPaymentsMoneyService.queryList(paymentsMoneyBo));
        });
        return outpFeesMasterVos;
    }

    /**
     * 查询门诊退费申请记录
     */
    @Override
    public OutpFeesMasterVo getRefundList(OutpFeesMasterBo bo) {
        initChargeFlagArray(bo);
        // 查询收费主记录
        List<OutpFeesMasterVo> outpFeesMasterVos = baseMapper.selectVoPage(bo);
        if (CollectionUtil.isNotEmpty(outpFeesMasterVos)) {
            OutpFeesMasterVo outpFeesMasterVo = outpFeesMasterVos.get(0);
            // 查询收费明细记录
            List<OutpFeesDetailVo> outpFeesDetailVos = outpFeesDetailMapper.selectVoList(Wrappers.<OutpFeesDetail>lambdaQuery()
                    .eq(OutpFeesDetail::getOutpFeesMasterId, outpFeesMasterVo.getOutpFeesMasterId())
            );
            //获取明细中的诊疗项目id
            List<String> clinicItemIds = outpFeesDetailVos.stream().map(OutpFeesDetailVo::getClinicItemId).collect(Collectors.toList());
            List<OutpFeesDetailVo> refundDetailGroupByList = outpFeesDetailMapper.getRefundDetailGroupBy(outpFeesMasterVo.getOrgId(),
                    BaseConstants.CHARGE_FLAG_DICT.THREE, outpFeesMasterVo.getOutpFeesMasterId());
            OutpFeesPaymentsMoneyBo paymentsMoneyBo = new OutpFeesPaymentsMoneyBo();
            paymentsMoneyBo.setFeesNo(outpFeesMasterVo.getFeesNo());
            paymentsMoneyBo.setOrgId(outpFeesMasterVo.getOrgId());
            List<OutpFeesPaymentsMoneyVo> outpFeesPaymentsMoneyVos = outpFeesPaymentsMoneyService.queryList(paymentsMoneyBo);
            outpFeesMasterVo.setPaymentsMoneyVoList(outpFeesPaymentsMoneyVos);
            refundDetailGroupByList.forEach(refundDetail -> {
                refundDetail.setPaymentsMoneyVoList(outpFeesPaymentsMoneyVos);
                refundDetail.setApplyDeptName(CollectionUtil.isNotEmpty(sysDeptMap) && StringUtils.isNotEmpty(refundDetail.getApplyDept())
                        ? sysDeptMap.get(refundDetail.getApplyDept()).getDeptName() : "");
                refundDetail.setImplementDeptName(CollectionUtil.isNotEmpty(sysDeptMap) && StringUtils.isNotEmpty(refundDetail.getImplementDept())
                        ? sysDeptMap.get(refundDetail.getImplementDept()).getDeptName() : "");
                // 通过clinicItemId和applyNo 匹配对应的价表项目明细
                List<OutpFeesDetailVo> collect = outpFeesDetailVos.stream()
                        .filter(detailVo -> StringUtils.equals(detailVo.getClinicItemId(), refundDetail.getClinicItemId())
                                && StringUtils.equals(detailVo.getApplyNo(), refundDetail.getApplyNo()))
                        .collect(Collectors.toList());
                refundDetail.setOutpFeesDetailVoList(collect);
            });
            outpFeesMasterVo.setDetailVoList(refundDetailGroupByList);
            return outpFeesMasterVo;
        }
        return null;
    }

    /**
     * 组织收费状态list
     *
     * @param bo
     */
    public void initChargeFlagArray(OutpFeesMasterBo bo) {
        String[] chargeFlagStr = null;
        if (StringUtils.isNotBlank(bo.getChargeFlagStr())) {
            chargeFlagStr = bo.getChargeFlagStr().split(",");
            bo.setChargeFlagArray(chargeFlagStr);
        }
    }

    private LambdaQueryWrapper<OutpFeesMaster> buildQueryWrapper(OutpFeesMasterBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<OutpFeesMaster> lqw = Wrappers.lambdaQuery();
        if (ObjectUtil.isNotNull(params.get("beginTime")) && ObjectUtil.isNotNull(params.get("endTime"))) {
            lqw.between(OutpFeesMaster::getCreateTime, DateUtils.parseDate(params.get("beginTime")), DateUtils.parseDate(params.get("endTime")));
        }
        lqw.eq(StringUtils.isNotBlank(bo.getOutpFeesMasterId()), OutpFeesMaster::getOutpFeesMasterId, bo.getOutpFeesMasterId());
        lqw.eq(StringUtils.isNotBlank(bo.getPatientId()), OutpFeesMaster::getPatientId, bo.getPatientId());
        lqw.eq(StringUtils.isNotBlank(bo.getClinicId()), OutpFeesMaster::getClinicId, bo.getClinicId());
        lqw.eq(bo.getVisitDate() != null, OutpFeesMaster::getVisitDate, bo.getVisitDate());
        lqw.eq(StringUtils.isNotBlank(bo.getOrdersId()), OutpFeesMaster::getOrdersId, bo.getOrdersId());
        lqw.like(StringUtils.isNotBlank(bo.getSerialNo()), OutpFeesMaster::getSerialNo, bo.getSerialNo());
        lqw.eq(StringUtils.isNotBlank(bo.getSerialNoParent()), OutpFeesMaster::getSerialNoParent, bo.getSerialNoParent());
//        lqw.eq(StringUtils.isNotBlank(bo.getSerialNo()), OutpFeesMaster::getSerialNo, bo.getSerialNo());
        lqw.eq(bo.getDiffCost() != null, OutpFeesMaster::getDiffCost, bo.getDiffCost());
//        lqw.eq(StringUtils.isNotBlank(bo.getChargeFlag()), OutpFeesMaster::getChargeFlag, bo.getChargeFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getRefundedFeesNo()), OutpFeesMaster::getRefundedFeesNo, bo.getRefundedFeesNo());
        lqw.eq(StringUtils.isNotBlank(bo.getRefundedPerson()), OutpFeesMaster::getRefundedPerson, bo.getRefundedPerson());
        lqw.eq(StringUtils.isNotBlank(bo.getAcctNo()), OutpFeesMaster::getAcctNo, bo.getAcctNo());
//        lqw.eq(StringUtils.isNotBlank(bo.getApplyUser()), OutpFeesMaster::getApplyUser, bo.getApplyUser());
//        lqw.eq(StringUtils.isNotBlank(bo.getApplyDept()), OutpFeesMaster::getApplyDept, bo.getApplyDept());
//        lqw.eq(StringUtils.isNotBlank(bo.getImplementDept()), OutpFeesMaster::getImplementDept, bo.getImplementDept());
//        lqw.eq(StringUtils.isNotBlank(bo.getImplementUser()), OutpFeesMaster::getImplementUser, bo.getImplementUser());
        lqw.eq(StringUtils.isNotBlank(bo.getOrgId()), OutpFeesMaster::getOrgId, bo.getOrgId());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks()), OutpFeesMaster::getRemarks, bo.getRemarks());
        lqw.eq(StringUtils.isNotBlank(bo.getYbSerialType()), OutpFeesMaster::getYbSerialType, bo.getYbSerialType());
        lqw.eq(StringUtils.isNotBlank(bo.getYbSerialNo()), OutpFeesMaster::getYbSerialNo, bo.getYbSerialNo());
        lqw.eq(StringUtils.isNotBlank(bo.getYbSerialData()), OutpFeesMaster::getYbSerialData, bo.getYbSerialData());
        lqw.eq(StringUtils.isNotBlank(bo.getInvoiceSerialNo()), OutpFeesMaster::getInvoiceSerialNo, bo.getInvoiceSerialNo());
        lqw.eq(StringUtils.isNotBlank(bo.getCanBaoType()), OutpFeesMaster::getCanBaoType, bo.getCanBaoType());
        return lqw;
    }

    /**
     * 新增门诊收费记录主
     */
    @Override
    @GlobalTransactional
    public Boolean insertByBo(FeesParamBo bo) {
        boolean okFlag = false;
        // 收费基本信息
        OutpFeesMasterBo outpFeesMasterBo = bo.getOutpFeesMasterBo();
        // 设置公共属性
        setPublicAttribute(outpFeesMasterBo);
        // 获取门诊待收费表id集合
        List<String> ordersIds = bo.getOrdersIdList();
        // 支付方式
        List<OutpFeesPaymentsMoney> payWayInfoList = bo.getPayWayInfoList();
        ClinicOrdersBo clinicOrdersBo = new ClinicOrdersBo();
        clinicOrdersBo.setOrdersIdArray(ordersIds);
        List<ClinicOrdersVo> clinicOrdersVos = clinicOrdersService.queryList(clinicOrdersBo);
        if (ordersIds.size() != clinicOrdersVos.size()) {
            throw new RuntimeException("已勾选的项目中，存在被医生删除的项目，不能收费，请刷新页面后重新收费。");
        }
        // 获取门诊医嘱明细
        ClinicOrdersCostBo clinicOrdersCostBo = new ClinicOrdersCostBo();
        clinicOrdersCostBo.setOrdersIdArray(ordersIds);
        List<ClinicOrdersCostVo> clinicOrdersCostVos = clinicOrdersCostService.queryList(clinicOrdersCostBo);
        return saveInfo(outpFeesMasterBo, clinicOrdersVos, clinicOrdersCostVos, payWayInfoList);
    }

    @Transactional
    public Boolean saveInfo(OutpFeesMasterBo outpFeesMasterBo, List<ClinicOrdersVo> clinicOrdersVos,
                            List<ClinicOrdersCostVo> clinicOrdersCostVos,
                            List<OutpFeesPaymentsMoney> payWayInfoList) {
        // 组织保存、收费主记录信息
        OutpFeesMaster outpFeesMaster = saveFeesMaster(outpFeesMasterBo, clinicOrdersVos);
        for (ClinicOrdersVo clinicOrdersVo : clinicOrdersVos) {
            if (!StringUtils.equals(clinicOrdersVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.ONE)) {
                throw new RuntimeException("申请单号为" + clinicOrdersVo.getApplyNo() + "的项目已收费，不能重复收费，请重新候选项目后重新收费");
            }
            // 根据ordersId获取对应的cost明细list
            List<ClinicOrdersCostVo> costVoCollect = clinicOrdersCostVos.stream()
                    .filter(e -> StringUtils.equals(e.getOrdersId(), clinicOrdersVo.getId())).collect(Collectors.toList());
            // 保存收费明细
            saveFeesDetail(outpFeesMaster, costVoCollect);
            // 修改门诊医嘱记录收费状态
            ClinicOrdersBo updateEntity = new ClinicOrdersBo();
            updateEntity.setId(clinicOrdersVo.getId());
            updateEntity.setIsApply(clinicOrdersVo.getIsApply());
            updateEntity.setChargeFlag(BaseConstants.CHARGE_FLAG_DICT.TWO);
            updateEntity.setApplyNo(clinicOrdersVo.getApplyNo());
            updateEntity.setOrgId(clinicOrdersVo.getOrgId());
            updateEntity.setFeesNo(outpFeesMasterBo.getFeesNo());
            clinicOrdersService.updateChargeFlag(updateEntity);
        }
        return savePaymentsMoney(outpFeesMaster, payWayInfoList);
    }

    /**
     * 设置公共属性
     *
     * @param outpFeesMasterBo
     */
    @Transactional
    public void setPublicAttribute(OutpFeesMasterBo outpFeesMasterBo) {
        // 获取结算流水号
        String outpFeesNo = remoteSerialNumberUtils.generateOutpFeesNo(outpFeesMasterBo.getOrgId());
        outpFeesMasterBo.setFeesNo(outpFeesNo);
        // 获取当前时间
        Date nowDate = DateUtils.getNowDate();
        // 同一次收费设置相同收费时间
        outpFeesMasterBo.setCreateTime(nowDate);
        outpFeesMasterBo.setUpdateTime(nowDate);
    }

    /**
     * 组织保存、收费主记录信息
     *
     * @param bo
     * @param clinicOrdersVos
     * @return
     */
    @Transactional
    public OutpFeesMaster saveFeesMaster(OutpFeesMasterBo bo, List<ClinicOrdersVo> clinicOrdersVos) {
        OutpFeesMaster outpFeesMaster = BeanUtil.toBean(bo, OutpFeesMaster.class);
        outpFeesMaster.initEntity();
        BigDecimal costsSum = BigDecimal.ZERO;
        BigDecimal chargesSum = BigDecimal.ZERO;
        for (ClinicOrdersVo vos : clinicOrdersVos) {
            costsSum = costsSum.add(vos.getCosts());
            chargesSum = chargesSum.add(vos.getCharges());
        }
        outpFeesMaster.setCosts(costsSum);
        outpFeesMaster.setCharges(chargesSum);

        outpFeesMaster.setOperationUser(LoginHelper.getLoginUser().getNickName());
        outpFeesMaster.setChargeFlag(BaseConstants.CHARGE_FLAG_DICT.TWO);
        baseMapper.insert(outpFeesMaster);
        return outpFeesMaster;
    }

    /**
     * 组织保存、收费cost明细信息
     *
     * @param outpFeesMaster 收费主记录
     * @param costVoCollect  门诊待收费明细
     */
    @Transactional
    public void saveFeesDetail(OutpFeesMaster outpFeesMaster, List<ClinicOrdersCostVo> costVoCollect) {
        List<OutpFeesDetail> outpFeesDetailList = new ArrayList<>();
        costVoCollect.forEach(costVo -> {
            OutpFeesDetail outpFeesDetail = BeanUtil.toBean(costVo, OutpFeesDetail.class);
            outpFeesDetail.setOutpFeesMasterId(outpFeesMaster.getOutpFeesMasterId());
            outpFeesDetail.setFeesNo(outpFeesMaster.getFeesNo());
            outpFeesDetail.setOutpFeesMasterId(outpFeesMaster.getOutpFeesMasterId());
            outpFeesDetail.setSerialNo(outpFeesMaster.getSerialNo());
            outpFeesDetail.setCreateTime(outpFeesMaster.getCreateTime());
            outpFeesDetail.setUpdateTime(outpFeesMaster.getUpdateTime());
            outpFeesDetail.setChargeFlag(BaseConstants.CHARGE_FLAG_DICT.TWO);
            outpFeesDetail.initEntity();
            outpFeesDetail.setApplyItemId(costVo.getApplyItemId());
            outpFeesDetail.setClinicItemId(costVo.getClinicItemId());
            outpFeesDetail.setClinicOrderId(costVo.getOrdersId());

            outpFeesDetailList.add(outpFeesDetail);
        });
        outpFeesDetailMapper.insertBatch(outpFeesDetailList);
    }

    /**
     * 组织保存、收费支付方式信息
     *
     * @param payWayInfoList
     * @return
     */
    @Transactional
    public boolean savePaymentsMoney(OutpFeesMaster outpFeesMaster, List<OutpFeesPaymentsMoney> payWayInfoList) {
        payWayInfoList.forEach(payWay -> {
            payWay.setOrgId(payWay.getOrgId());
            payWay.setFeesNo(outpFeesMaster.getFeesNo());
            payWay.setCreateTime(outpFeesMaster.getCreateTime());
            payWay.setUpdateTime(outpFeesMaster.getUpdateTime());
            payWay.setOutpFeesMasterId(outpFeesMaster.getOutpFeesMasterId());
            payWay.initEntity();
        });
        return outpFeesPaymentsMoneyMapper.insertBatch(payWayInfoList);
    }

    /**
     * 修改门诊收费记录主
     */
    @Override
    public Boolean updateByBo(OutpFeesMasterBo bo) {
        OutpFeesMaster update = BeanUtil.toBean(bo, OutpFeesMaster.class);
        update.updateInfo();
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(OutpFeesMaster entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除门诊收费记录主
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }


    @Override
    @Transactional
    public Boolean updateChargeFlag(OutpFeesMasterBo bo) {
        return baseMapper.update(null, Wrappers.<OutpFeesMaster>lambdaUpdate()
                .set(OutpFeesMaster::getChargeFlag, bo.getChargeFlag())
                .eq(StringUtils.isNotBlank(bo.getOrdersId()), OutpFeesMaster::getOrdersId, bo.getOrdersId())
                .eq(StringUtils.isNotBlank(bo.getOutpFeesMasterId()), OutpFeesMaster::getOutpFeesMasterId, bo.getOutpFeesMasterId())
        ) > 0;
    }

    /**
     * 修改收费状态 ：3->申请退费
     *
     * @param feesOrApplyOrApplyItemId feesNo或applyNo或applyItemId
     * @param type                     单个退费和全部退费状态 (单个：single 全部：all)
     * @return
     */
    @Override
    public Boolean refundApplication(String feesOrApplyOrApplyItemId, String chargeFlag, String type, String orgId, String feesNoParam) {
        OutpFeesMasterVo outpFeesMasterVo = null;
        // 收据号
        String feesNo = "";
        // 申请号
        String applyNo = "";
        // 收费明细
        List<String> applyItemIdList = new ArrayList<>();
        List<String> chargeFlags = new ArrayList<>();
        if (StringUtils.equals(chargeFlag, BaseConstants.CHARGE_FLAG_DICT.TWO)) {
            chargeFlags.add(BaseConstants.CHARGE_FLAG_DICT.THREE);
        }
        if (StringUtils.equals(chargeFlag, BaseConstants.CHARGE_FLAG_DICT.THREE)) {
            chargeFlags.add(BaseConstants.CHARGE_FLAG_DICT.TWO);
        }
        chargeFlags.add(BaseConstants.CHARGE_FLAG_DICT.SIX);
        // 查询收费明细
        List<OutpFeesDetailVo> outpFeesDetailVos = getDetailVoList(orgId, feesOrApplyOrApplyItemId, type, chargeFlags, feesNoParam);
        // 主记录收费状态字段
        String masterChargeFlag = chargeFlag;
        // 门诊医嘱收费状态字段
        String ordersChargeFlag = chargeFlag;

        if (StringUtils.equals(BaseConstants.ITEM_REFUND_OR_CANCEL.ALL, type)) {
            // 全部
            // 获取主记录
            outpFeesMasterVo = getMasterVo(feesOrApplyOrApplyItemId, orgId);
            feesNo = feesOrApplyOrApplyItemId;
        } else if (StringUtils.equals(BaseConstants.ITEM_REFUND_OR_CANCEL.APPLY, type)) {
            // 按申请单
            // 获取主记录
            outpFeesMasterVo = getMasterVo(outpFeesDetailVos.get(0).getFeesNo(), orgId);
            feesNo = outpFeesMasterVo.getFeesNo();

        } else if (StringUtils.equals(BaseConstants.ITEM_REFUND_OR_CANCEL.SINGLE, type)) {
            // 按项目
            // 按申请单
            if (CollectionUtil.isNotEmpty(outpFeesDetailVos)) {
                ordersChargeFlag = BaseConstants.CHARGE_FLAG_DICT.SEVEN;
                // 获取主记录
                outpFeesMasterVo = getMasterVo(outpFeesDetailVos.get(0).getFeesNo(), orgId);
                feesNo = outpFeesMasterVo.getFeesNo();
                applyNo = outpFeesDetailVos.get(0).getApplyNo();
            }
        }
        applyItemIdList = outpFeesDetailVos.stream().map(OutpFeesDetailVo::getApplyItemId).collect(Collectors.toList());
        /* ********************   开始修改   **********************/
        if (ObjectUtil.isNotNull(outpFeesMasterVo)) {
            List<OutpFeesDetailVo> outpFeesDetailVos1 = outpFeesDetailMapper.selectVoList(Wrappers.<OutpFeesDetail>lambdaQuery()
                    .in(OutpFeesDetail::getApplyItemId, applyItemIdList)
            );
            outpFeesDetailVos1.forEach(outpFeesDetailVo -> {
                // 修改收费明细表
                outpFeesDetailMapper.update(null, new LambdaUpdateWrapper<OutpFeesDetail>()
                        .set(OutpFeesDetail::getChargeFlag, StringUtils.equals(outpFeesDetailVo.getConfirmFlag(), BaseConstants.CONFIRM_FLAG.ISSUED)
                                && !StringUtils.equals(outpFeesDetailVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.SIX) ?
                                BaseConstants.CHARGE_FLAG_DICT.SIX : chargeFlag)
                        .eq(OutpFeesDetail::getOutpFeesDetailId, outpFeesDetailVo.getOutpFeesDetailId())
                );
            });
            List<String> chargeFlagsCount = new ArrayList<>();
            chargeFlagsCount.add(chargeFlag);
            chargeFlagsCount.add(BaseConstants.CHARGE_FLAG_DICT.SIX);
            int feesNoGroupCount = outpFeesDetailMapper.getFeesNoGroupCount(feesNo, chargeFlagsCount, orgId);
            if (feesNoGroupCount != 0) {
                masterChargeFlag = BaseConstants.CHARGE_FLAG_DICT.SEVEN;
            } else {
                masterChargeFlag = chargeFlag;
            }
            if (StringUtils.equals(BaseConstants.ITEM_REFUND_OR_CANCEL.SINGLE, type)) {
                int applyNoGroupCount = outpFeesDetailMapper.getApplyNoGroupCount(applyNo, chargeFlagsCount, orgId);
                if (applyNoGroupCount != 0) {
                    ordersChargeFlag = BaseConstants.CHARGE_FLAG_DICT.SEVEN;
                } else {
                    ordersChargeFlag = chargeFlag;
                }
            }
            // 修改收费主表
            baseMapper.update(null, new LambdaUpdateWrapper<OutpFeesMaster>()
                    .set(OutpFeesMaster::getChargeFlag, masterChargeFlag)
                    .eq(OutpFeesMaster::getOutpFeesMasterId, outpFeesMasterVo.getOutpFeesMasterId())
            );

            List<ClinicOrdersCostVo> clinicOrdersCostVos = clinicOrdersCostMapper.selectVoList(Wrappers.<ClinicOrdersCost>lambdaQuery()
                    .in(ClinicOrdersCost::getApplyItemId, applyItemIdList)
                    .eq(ClinicOrdersCost::getOrgId, orgId)
            );
            for (ClinicOrdersCostVo clinicOrdersCostVo : clinicOrdersCostVos) {
                // 修改门诊医嘱明细表
                clinicOrdersCostMapper.update(null, new LambdaUpdateWrapper<ClinicOrdersCost>()
                        .set(ClinicOrdersCost::getChargeFlag, StringUtils.equals(clinicOrdersCostVo.getConfirmFlag(), BaseConstants.CONFIRM_FLAG.ISSUED)
                                && !StringUtils.equals(clinicOrdersCostVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.SIX) ?
                                BaseConstants.CHARGE_FLAG_DICT.SIX : chargeFlag)
                        .eq(ClinicOrdersCost::getApplyItemId, clinicOrdersCostVo.getApplyItemId())
                        .eq(ClinicOrdersCost::getOrgId, orgId)
                );
            }
            List<String> orderIds = clinicOrdersCostVos.stream().map(ClinicOrdersCostVo::getOrdersId).collect(Collectors.toList());
            List<ClinicOrdersVo> clinicOrdersVos = clinicOrdersMapper.selectVoList(Wrappers.<ClinicOrders>lambdaQuery()
                    .in(ClinicOrders::getId, orderIds)
            );
            for (ClinicOrdersVo clinicOrdersVo : clinicOrdersVos) {
                // 修改门诊医嘱表
                clinicOrdersMapper.update(null, new LambdaUpdateWrapper<ClinicOrders>()
                        .set(ClinicOrders::getChargeFlag, StringUtils.equals(clinicOrdersVo.getConfirmFlag(), BaseConstants.CONFIRM_FLAG.ISSUED)
                                && !StringUtils.equals(clinicOrdersVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.SIX) ?
                                BaseConstants.CHARGE_FLAG_DICT.SIX : chargeFlag)
                        .eq(ClinicOrders::getId, clinicOrdersVo.getId())
                        .eq(ClinicOrders::getOrgId, orgId)
                );
            }
            // 修改门诊处置治疗表
            outpTreatRecMapper.update(null, new LambdaUpdateWrapper<OutpTreatRec>()
                    .set(OutpTreatRec::getChargeFlag, chargeFlag)
                    .in(OutpTreatRec::getApplyItemId, applyItemIdList)
            );
            updateBusinessChargeType(type, orgId, ordersChargeFlag, chargeFlag, outpFeesDetailVos);
        }
        return Boolean.TRUE;
    }

    /**
     * 修改业务数据
     */
    @Transactional
    public void updateBusinessChargeType(String type, String orgId,
                                         String ordersChargeFlag, String chargeFlag,
                                         List<OutpFeesDetailVo> outpFeesDetailVos) {
        //根据ApplyItemId去重
        outpFeesDetailVos = outpFeesDetailVos.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                new TreeSet<>(Comparator.comparing(OutpFeesDetailVo::getApplyItemId))), ArrayList::new));
        List<String> applyNos = outpFeesDetailVos.stream().map(OutpFeesDetailVo::getApplyNo).collect(Collectors.toList());
        applyNos = applyNos.stream().distinct().collect(Collectors.toList());
        for (String applyNo : applyNos) {
            String applyNoPrefix = applyNo.substring(0, 2);
            switch (Integer.parseInt(applyNoPrefix)) {
                case SerialNumberConstants.CLINIC_EXAM_NO:
                    // 修改检查主记录
                    List<ExamApplyVo> examApplyVos = examApplyMapper.selectVoList(Wrappers.<ExamApply>lambdaQuery()
                            .eq(ExamApply::getApplyNo, applyNo)
                            .eq(ExamApply::getOrgId, orgId)
                    );
                    examApplyVos.forEach(examApplyVo -> {
                        examApplyMapper.update(null, new LambdaUpdateWrapper<ExamApply>()
                                .set(ExamApply::getChargeFlag, StringUtils.equals(examApplyVo.getConfirmFlag(), BaseConstants.CONFIRM_FLAG.ISSUED)
                                        && !StringUtils.equals(examApplyVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.SIX)
                                        && !StringUtils.equals(examApplyVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.THREE)
                                        ? BaseConstants.CHARGE_FLAG_DICT.SIX : ordersChargeFlag)
                                .eq(ExamApply::getId, examApplyVo.getId())
                                .eq(ExamApply::getOrgId, orgId)
                        );
                    });
                    break;
                case SerialNumberConstants.CLINIC_LAB_NO:
                    // 修改检查主记录
                    List<LabApplyVo> labApplyVos = labApplyMapper.selectVoList(Wrappers.<LabApply>lambdaQuery()
                            .eq(LabApply::getApplyNo, applyNo)
                            .eq(LabApply::getOrgId, orgId)
                    );
                    labApplyVos.forEach(labApplyVo -> {
                        labApplyMapper.update(null, new LambdaUpdateWrapper<LabApply>()
                                .set(LabApply::getChargeFlag, StringUtils.equals(labApplyVo.getConfirmFlag(), BaseConstants.CONFIRM_FLAG.ISSUED)
                                        && !StringUtils.equals(labApplyVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.SIX)
                                        && !StringUtils.equals(labApplyVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.THREE)
                                        ? BaseConstants.CHARGE_FLAG_DICT.SIX : ordersChargeFlag)
                                .eq(LabApply::getId, labApplyVo.getId())
                                .eq(LabApply::getOrgId, orgId)
                        );
                    });
                    break;
                case SerialNumberConstants.CLINIC_PRESCRIPTION_NO:
                    List<PrescriptionApplyVo> prescriptionApplyVos = prescriptionApplyMapper.selectVoList(Wrappers.<PrescriptionApply>lambdaQuery()
                            .eq(PrescriptionApply::getApplyNo, applyNo)
                            .eq(PrescriptionApply::getOrgId, orgId)
                    );
                    prescriptionApplyVos.forEach(prescriptionApplyVo -> {
                        prescriptionApplyMapper.update(null, new LambdaUpdateWrapper<PrescriptionApply>()
                                .set(PrescriptionApply::getChargeFlag, StringUtils.equals(prescriptionApplyVo.getConfirmFlag(), BaseConstants.CONFIRM_FLAG.ISSUED)
                                        && !StringUtils.equals(prescriptionApplyVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.SIX)
                                        && !StringUtils.equals(prescriptionApplyVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.THREE)
                                        ? BaseConstants.CHARGE_FLAG_DICT.SIX : ordersChargeFlag)
                                .eq(PrescriptionApply::getApplyId, prescriptionApplyVo.getApplyId())
                                .eq(PrescriptionApply::getOrgId, orgId)
                        );
                    });
                    break;
                default:
                    break;
            }
        }
        for (OutpFeesDetailVo detailVo : outpFeesDetailVos) {
            String applyNoPrefix = detailVo.getApplyNo().substring(0, 2);
            switch (Integer.parseInt(applyNoPrefix)) {
                case SerialNumberConstants.CLINIC_EXAM_NO:
                    // 修改检查明细
                    List<ExamItemVo> examItemVos = examItemMapper.selectVoList(Wrappers.<ExamItem>lambdaQuery()
                            .eq(ExamItem::getId, detailVo.getApplyItemId())
                            .eq(ExamItem::getOrgId, detailVo.getOrgId())
                    );
                    examItemVos.forEach(examItemVo -> {
                        examItemMapper.update(null, new LambdaUpdateWrapper<ExamItem>()
                                .set(ExamItem::getChargeFlag, StringUtils.equals(examItemVo.getConfirmFlag(), BaseConstants.CONFIRM_FLAG.ISSUED)
                                        && !StringUtils.equals(examItemVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.SIX)
                                        && !StringUtils.equals(examItemVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.THREE)
                                        ? BaseConstants.CHARGE_FLAG_DICT.SIX : ordersChargeFlag)
                                .eq(ExamItem::getId, examItemVo.getId())
                        );
                    });
                    break;
                case SerialNumberConstants.CLINIC_LAB_NO:
                    // 修改检验信息
                    // 修改检验明细
                    List<LabItemVo> labItemVos = labItemMapper.selectVoList(Wrappers.<LabItem>lambdaQuery()
                            .eq(LabItem::getId, detailVo.getApplyItemId())
                            .eq(LabItem::getOrgId, detailVo.getOrgId())
                    );
                    labItemVos.forEach(labItemVo -> {
                        labItemMapper.update(null, new LambdaUpdateWrapper<LabItem>()
                                .set(LabItem::getChargeFlag, StringUtils.equals(labItemVo.getConfirmFlag(), BaseConstants.CONFIRM_FLAG.ISSUED)
                                        && !StringUtils.equals(labItemVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.SIX)
                                        && !StringUtils.equals(labItemVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.THREE)
                                        ? BaseConstants.CHARGE_FLAG_DICT.SIX : ordersChargeFlag)
                                .eq(LabItem::getId, labItemVo.getId())
                        );
                    });

                    break;
                case SerialNumberConstants.CLINIC_PRESCRIPTION_NO:
                    // 修改处方明细
                    List<PrescriptionItemVo> prescriptionItemVos = prescriptionItemMapper.selectVoList(Wrappers.<PrescriptionItem>lambdaQuery()
                            .eq(PrescriptionItem::getItemId, detailVo.getApplyItemId())
                            .eq(PrescriptionItem::getOrgId, detailVo.getOrgId())
                    );
                    prescriptionItemVos.forEach(itemVo -> {
                        // 修改检查明细
                        prescriptionItemMapper.update(null, new LambdaUpdateWrapper<PrescriptionItem>()
                                .set(PrescriptionItem::getChargeFlag, StringUtils.equals(itemVo.getConfirmFlag(), BaseConstants.CONFIRM_FLAG.ISSUED)
                                        && !StringUtils.equals(itemVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.SIX)
                                        && !StringUtils.equals(itemVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.THREE)
                                        ? BaseConstants.CHARGE_FLAG_DICT.SIX : ordersChargeFlag)
                                .eq(PrescriptionItem::getItemId, itemVo.getItemId())
                        );
                    });
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 根据条件设置需要修改的chargeFlag值
     * @param confirmFlag
     * @param chargeFlag
     * @param ordersChargeFlag
     * @return
     */
//    public String setChargeFlag(String confirmFlag, String chargeFlag, String ordersChargeFlag) {
//        String retOrdersChargeFlag = ordersChargeFlag;
//        if (StringUtils.equals(confirmFlag, BaseConstants.CONFIRM_FLAG.UNISSUED)) {
//            // 未发放
//            return retOrdersChargeFlag;
//        } else if (StringUtils.equals(confirmFlag, BaseConstants.CONFIRM_FLAG.ISSUED)) {
//            // 已发放
//            if (StringUtils.equals(chargeFlag, BaseConstants.CHARGE_FLAG_DICT.SIX)) {
//
//            }
//        } else {
//
//        }
//    }

    /**
     * 查询门诊收费主记录
     *
     * @param getFeesNo
     * @param orgId
     * @return
     */
    public OutpFeesMasterVo getMasterVo(String getFeesNo, String orgId) {
        return baseMapper.selectVoOne(Wrappers.<OutpFeesMaster>lambdaQuery()
                .eq(OutpFeesMaster::getFeesNo, getFeesNo)
                .eq(OutpFeesMaster::getOrgId, orgId));
    }

    /**
     * 查询门诊收费明细
     *
     * @param orgId
     * @param feesOrApplyOrApplyItemId feesNo或applyNo或applyItemId
     * @param type
     * @return
     */
    public List<OutpFeesDetailVo> getDetailVoList(String orgId, String feesOrApplyOrApplyItemId, String
            type, List<String> chargeTypes, String feesNoParam) {
        return outpFeesDetailMapper.selectVoList(Wrappers.<OutpFeesDetail>lambdaQuery()
                // 如果为all ，通过主表id查询
                .eq(StringUtils.equals(BaseConstants.ITEM_REFUND_OR_CANCEL.ALL, type),
                        OutpFeesDetail::getFeesNo, feesOrApplyOrApplyItemId)
                // 如果为apply ，通过applyNo查询
                .eq(StringUtils.equals(BaseConstants.ITEM_REFUND_OR_CANCEL.APPLY, type),
                        OutpFeesDetail::getApplyNo, feesOrApplyOrApplyItemId)
                // 如果为single ， 通过applyItemId查询
                .eq(StringUtils.equals(BaseConstants.ITEM_REFUND_OR_CANCEL.SINGLE, type),
                        OutpFeesDetail::getApplyItemId, feesOrApplyOrApplyItemId)
                .eq(OutpFeesDetail::getOrgId, orgId)
                .eq(OutpFeesDetail::getFeesNo, feesNoParam)
                .in(OutpFeesDetail::getChargeFlag, chargeTypes)
        );
    }

    /**
     * 确认退费
     *
     * @param bo
     * @return
     */
    @Override
    @GlobalTransactional
    public Boolean confirmationRefund(FeesParamBo bo) {
        // 退费确认项目是否全部勾选 Y是 ，N
        String isAllCheck = bo.getIsAllCheck();
        List<String> applyItemIdList = bo.getApplyItemIdList();
        String oldOutpFeesMasterId = bo.getOutpFeesMasterBo().getOutpFeesMasterId();
        // 通过applyItemId查询明细信息
        List<OutpFeesDetailVo> outpFeesDetailVos = outpFeesDetailMapper.selectVoList(Wrappers.<OutpFeesDetail>lambdaQuery()
                .in(OutpFeesDetail::getApplyItemId, applyItemIdList)
                .eq(OutpFeesDetail::getChargeFlag, BaseConstants.CHARGE_FLAG_DICT.THREE)
        );
        if (CollectionUtil.isEmpty(outpFeesDetailVos)) {
            throw new RuntimeException("勾选的退费项目收费状态已改变，不能继续退费，请刷新页面。");
        }
        // 查询需要退费的信息主记录
        OutpFeesMasterVo outpFeesMasterVo = baseMapper.selectVoById(bo.getOutpFeesMasterBo().getOutpFeesMasterId());
        if (!StringUtils.equals(outpFeesMasterVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.SEVEN)
                && !StringUtils.equals(outpFeesMasterVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.THREE)) {
            throw new RuntimeException("申请单收费状态已改变，不能继续退费，请刷新页面。");
        }
        // 复制需要新增的负记录
        OutpFeesMasterBo refundMasterBo = BeanUtil.toBean(outpFeesMasterVo, OutpFeesMasterBo.class);
        setPublicAttribute(refundMasterBo);
        // 退费申请号
        String refundedFeesNo = refundMasterBo.getFeesNo();
        // orgId
        String orgId = outpFeesMasterVo.getOrgId();
        // 修改门诊收费主表信息
        baseMapper.update(null, new LambdaUpdateWrapper<OutpFeesMaster>()
                        // 设置收费状态为 已退费
                        .set(
//                        StringUtils.equals(isAllCheck, UserConstants.YES),
                                OutpFeesMaster::getChargeFlag, BaseConstants.CHARGE_FLAG_DICT.FOUR)
                        // 设置退费号
                        .set(OutpFeesMaster::getRefundedFeesNo, refundedFeesNo)
                        // 设置退费人
                        .set(OutpFeesMaster::getRefundedPerson, LoginHelper.getLoginUser().getNickName())
                        .eq(OutpFeesMaster::getOutpFeesMasterId, outpFeesMasterVo.getOutpFeesMasterId())
        );
        refundMasterBo.setRefundedPerson(LoginHelper.getLoginUser().getNickName());
        // 判断前台勾选的项目 是否全部勾选
        //当为全部退费，整体需改clinicOrders收费状态为 3 已退费
        List<String> clinicOrdersList = outpFeesDetailVos.stream().map(OutpFeesDetailVo::getClinicOrderId).collect(Collectors.toList());
        clinicOrdersMapper.update(null, new LambdaUpdateWrapper<ClinicOrders>()
                .set(StringUtils.equals(isAllCheck, UserConstants.YES),
                        ClinicOrders::getChargeFlag, BaseConstants.CHARGE_FLAG_DICT.FOUR)
                .set(ClinicOrders::getFeesNo, refundedFeesNo)
                .in(ClinicOrders::getId, clinicOrdersList)
                .eq(ClinicOrders::getOrgId, orgId)
        );
        clinicOrdersCostMapper.update(null, new LambdaUpdateWrapper<ClinicOrdersCost>()
                .set(ClinicOrdersCost::getChargeFlag, BaseConstants.CHARGE_FLAG_DICT.FOUR)
                .in(ClinicOrdersCost::getApplyItemId, applyItemIdList)
                .eq(ClinicOrdersCost::getOrgId, orgId)

        );
        outpFeesDetailMapper.update(null, new LambdaUpdateWrapper<OutpFeesDetail>()
                .set(OutpFeesDetail::getChargeFlag, BaseConstants.CHARGE_FLAG_DICT.FOUR)
                .in(OutpFeesDetail::getApplyItemId, applyItemIdList)
                .eq(OutpFeesDetail::getOrgId, orgId)
        );
        // 修改业务数据
        updateBusinessChargeType(BaseConstants.ITEM_REFUND_OR_CANCEL.ALL, orgId,
                StringUtils.equals(isAllCheck, UserConstants.YES) ? BaseConstants.CHARGE_FLAG_DICT.FOUR : BaseConstants.CHARGE_FLAG_DICT.THREE,
                BaseConstants.CHARGE_FLAG_DICT.FOUR,
                outpFeesDetailVos);
        // 新增退费负记录
        addNegativeRecord(refundMasterBo, oldOutpFeesMasterId);
        if (StringUtils.equals(isAllCheck, UserConstants.NO)
                || StringUtils.equals(outpFeesMasterVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.SEVEN)) {
            insertNotRefundItem(bo, outpFeesMasterVo, refundedFeesNo);
        }
        return Boolean.TRUE;
    }

    /**
     * 新增退费负记录
     */
    @Transactional
    public void addNegativeRecord(OutpFeesMasterBo refundMasterBo, String oldOutpFeesMasterId) {

        refundMasterBo.setOutpFeesMasterId("");
        refundMasterBo.setChargeFlag(BaseConstants.CHARGE_FLAG_DICT.FOUR);
        refundMasterBo.setCosts(BigDecimal.ZERO.subtract(refundMasterBo.getCosts()));
        refundMasterBo.setCharges(BigDecimal.ZERO.subtract(refundMasterBo.getCharges()));
        refundMasterBo.setRefundedFeesNo("");
        refundMasterBo.setRefundedPerson("");
        OutpFeesMaster outpFeesMaster = BeanUtil.toBean(refundMasterBo, OutpFeesMaster.class);
        outpFeesMaster.initEntity();
        boolean b = baseMapper.insert(outpFeesMaster) > 0;
        if (b) {
            refundMasterBo.setOutpFeesMasterId(outpFeesMaster.getOutpFeesMasterId());
        }
        List<OutpFeesDetailVo> outpFeesDetailVos = outpFeesDetailMapper.selectVoList(Wrappers.<OutpFeesDetail>lambdaQuery()
                .eq(OutpFeesDetail::getOutpFeesMasterId, oldOutpFeesMasterId)
        );
        // 复制明细数据
        List<OutpFeesDetail> outpFeesDetail = BeanUtil.copyToList(outpFeesDetailVos, OutpFeesDetail.class);
        saveDetail(outpFeesDetail, refundMasterBo);

        // 新增支付方式
        List<OutpFeesPaymentsMoney> outpFeesPaymentsMoneyList = outpFeesPaymentsMoneyMapper.selectList(Wrappers.<OutpFeesPaymentsMoney>lambdaQuery()
                .eq(OutpFeesPaymentsMoney::getOutpFeesMasterId, oldOutpFeesMasterId)
        );
        saveMoney(outpFeesPaymentsMoneyList, refundMasterBo);
    }

    public void saveMoney(List<OutpFeesPaymentsMoney> outpFeesPaymentsMoneyList, OutpFeesMasterBo refundMasterBo) {
        outpFeesPaymentsMoneyList.forEach(money -> {
            money.setOutpFeesPaymentsId("");
            money.setOutpFeesMasterId(refundMasterBo.getOutpFeesMasterId());
            money.setCharges(BigDecimal.ZERO.subtract(money.getCharges()));
            money.setFeesNo(refundMasterBo.getFeesNo());
            money.setCreateTime(DateUtils.getNowDate());
            money.setUpdateTime(DateUtils.getNowDate());
            money.setCreateBy(LoginHelper.getLoginUser().getNickName());
            money.setUpdateBy(LoginHelper.getLoginUser().getNickName());
            money.initEntity();
        });
        outpFeesPaymentsMoneyMapper.insertBatch(outpFeesPaymentsMoneyList);
    }

    public void saveDetail(List<OutpFeesDetail> outpFeesDetail, OutpFeesMasterBo refundMasterBo) {
        outpFeesDetail.forEach(detail -> {
            detail.setOutpFeesDetailId("");
            detail.setOutpFeesMasterId(refundMasterBo.getOutpFeesMasterId());
            detail.setFeesNo(refundMasterBo.getFeesNo());
            detail.setCosts(BigDecimal.ZERO.subtract(detail.getCosts()));
            detail.setCharges(BigDecimal.ZERO.subtract(detail.getCharges()));
            detail.setNum(0 - detail.getNum());
            detail.setChargeFlag(BaseConstants.CHARGE_FLAG_DICT.FOUR);
            detail.setCreateTime(DateUtils.getNowDate());
            detail.setUpdateTime(DateUtils.getNowDate());
            detail.setCreateBy(LoginHelper.getLoginUser().getNickName());
            detail.setUpdateBy(LoginHelper.getLoginUser().getNickName());
            detail.initEntity();
        });
        outpFeesDetailMapper.insertBatch(outpFeesDetail);
    }

    public void insertNotRefundItem(FeesParamBo bo, OutpFeesMasterVo outpFeesMasterVo, String oldFeesNo) {
        List<OutpFeesDetailVo> outpFeesDetailVos = outpFeesDetailMapper.selectVoList(Wrappers.<OutpFeesDetail>lambdaQuery()
                .notIn(OutpFeesDetail::getApplyItemId, bo.getApplyItemIdList())
                .eq(OutpFeesDetail::getOutpFeesMasterId, outpFeesMasterVo.getOutpFeesMasterId())
        );
        BigDecimal costsSum = BigDecimal.ZERO;
        BigDecimal chargesSum = BigDecimal.ZERO;
        String chargeFlagMaster = BaseConstants.CHARGE_FLAG_DICT.TWO;
        for (OutpFeesDetailVo detailVo : outpFeesDetailVos) {
            chargesSum = chargesSum.add(detailVo.getCharges());
            costsSum = costsSum.add(detailVo.getCosts());
            if (StringUtils.equals(detailVo.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.THREE)) {
                chargeFlagMaster = BaseConstants.CHARGE_FLAG_DICT.SEVEN;
            }
        }
        OutpFeesMasterBo nowMasterBo = BeanUtil.toBean(outpFeesMasterVo, OutpFeesMasterBo.class);
        nowMasterBo.setChargeFlag(chargeFlagMaster);
        nowMasterBo.setOutpFeesMasterId("");
        nowMasterBo.setRefundedFeesNo("");
        nowMasterBo.setRefundedPerson("");
        nowMasterBo.setOperationUser(LoginHelper.getLoginUser().getNickName());
        nowMasterBo.setRefundCharges(nowMasterBo.getCharges().subtract(chargesSum));
        nowMasterBo.setCreateTime(DateUtils.getNowDate());
        nowMasterBo.setUpdateTime(DateUtils.getNowDate());
        nowMasterBo.setCreateBy(LoginHelper.getLoginUser().getNickName());
        nowMasterBo.setUpdateBy(LoginHelper.getLoginUser().getNickName());
        setPublicAttribute(nowMasterBo);
        OutpFeesMaster newMaster = BeanUtil.toBean(nowMasterBo, OutpFeesMaster.class);
        newMaster.initEntity();
        baseMapper.insert(newMaster);
        List<OutpFeesDetail> outpFeesDetailList = BeanUtil.copyToList(outpFeesDetailVos, OutpFeesDetail.class);
        for (OutpFeesDetail detail : outpFeesDetailList) {
            detail.setOutpFeesDetailId("");
            detail.setOutpFeesMasterId(newMaster.getOutpFeesMasterId());
            detail.setFeesNo(newMaster.getFeesNo());
            detail.setChargeFlag(StringUtils.equals(detail.getChargeFlag(), BaseConstants.CHARGE_FLAG_DICT.THREE) ?
                    BaseConstants.CHARGE_FLAG_DICT.THREE : BaseConstants.CHARGE_FLAG_DICT.TWO);
            detail.setCreateTime(DateUtils.getNowDate());
            detail.setUpdateTime(DateUtils.getNowDate());
            detail.setCreateBy(LoginHelper.getLoginUser().getNickName());
            detail.setUpdateBy(LoginHelper.getLoginUser().getNickName());
            detail.initEntity();
        }
        outpFeesDetailMapper.insertBatch(outpFeesDetailList);
        // 新增支付方式
        List<OutpFeesPaymentsMoney> outpFeesPaymentsMoneyList = bo.getPayWayInfoList();
        outpFeesPaymentsMoneyList.forEach(money -> {
            money.setOutpFeesPaymentsId("");
            money.setOutpFeesMasterId(newMaster.getOutpFeesMasterId());
            money.setCharges(money.getCharges());
            money.setFeesNo(newMaster.getFeesNo());
            money.setCreateTime(DateUtils.getNowDate());
            money.setUpdateTime(DateUtils.getNowDate());
            money.setCreateBy(LoginHelper.getLoginUser().getNickName());
            money.setUpdateBy(LoginHelper.getLoginUser().getNickName());
            money.initEntity();
        });
        outpFeesPaymentsMoneyMapper.insertBatch(outpFeesPaymentsMoneyList);
        List<String> clinicOrdersList = outpFeesDetailVos.stream().map(OutpFeesDetailVo::getClinicOrderId).collect(Collectors.toList());

        clinicOrdersMapper.update(null, new LambdaUpdateWrapper<ClinicOrders>()
                .set(ClinicOrders::getFeesNo, nowMasterBo.getFeesNo())
                .in(ClinicOrders::getId, clinicOrdersList)
                .eq(ClinicOrders::getOrgId, nowMasterBo.getOrgId())
        );
    }

    @Override
    public List<ClinicOrdersVo> listClinicOrders(OutpFeesMasterBo bo) {
        List<OutpFeesDetailVo> outpFeesDetailVos = outpFeesDetailMapper.selectVoList(Wrappers.<OutpFeesDetail>lambdaQuery()
                .eq(OutpFeesDetail::getFeesNo, bo.getFeesNo())
                .eq(OutpFeesDetail::getOrgId, bo.getOrgId())
        );
        List<String> clinicOrdersList = outpFeesDetailVos.stream().map(OutpFeesDetailVo::getClinicOrderId).collect(Collectors.toList());
        ClinicOrdersBo clinicOrdersBo = new ClinicOrdersBo();
        clinicOrdersBo.setOrdersIdArray(clinicOrdersList);
        List<ClinicOrdersVo> clinicOrdersVos = clinicOrdersService.queryList(clinicOrdersBo);
//        clinicOrdersVos.forEach(vo -> {
//            // 用于判断前台列表 申请退费按钮是否显示
//            vo.setIsShowButton(StringUtils.isNotEmpty(bo.getRefundedFeesNo()));
//            vo.getClinicOrdersCostVoList().forEach(costVo->{
//                // 用于判断前台列表 申请退费按钮是否显示
//                costVo.setIsShowButton(StringUtils.isNotEmpty(bo.getRefundedFeesNo()));
//            });
//        });
        return clinicOrdersVos;
    }
}
